/** \file qwwdic.cpp
 * \brief QWordWizard Dictionary implementation
 */

#include "qwwdic.h"
#include <stdlib.h>
#include <memory>
#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QStringList>

QWWDic *QWWDic::mp_instance = NULL;
QMutex QWWDic::m_mutex;

static QString loading_error = QObject::tr("Can't load dictionary");
static QString bad_format = QObject::tr("This file is not a dictionary file");

QWWDic *QWWDic::Instance()
{
    if (!mp_instance)
    {
        m_mutex.lock();
        if (!mp_instance)
        {
            mp_instance = new QWWDic();
            ::atexit(destroy);
        }
    }    
    return mp_instance;
}

QWWDic::QWWDic()
{
    qsrand ((int)QDateTime::currentMSecsSinceEpoch());
}

QWWDic::~QWWDic()
{

}

void QWWDic::destroy()
{
    delete mp_instance;
}

bool QWWDic::Reload()
{
    for (vector<QWWDic_t>::iterator it = m_dictionaries.begin(); it != m_dictionaries.end(); ++it)
    {
        try
        {
            LoadCSV(&(*it));
        }
        catch (exception)
        {
            return false;
        }
    }
    return true;
}

QString QWWDic::Preload(QString filename, DictionaryType type) const throw (runtime_error)
{
    QString description;
    switch (type)
    {
        case e_xml:
            {
			    QDomDocument doc;
			    auto_ptr<QFile> file(new QFile(filename));
			    if (!file->open(QIODevice::ReadOnly))
			        throw runtime_error(loading_error.toStdString());
			
			    if (!doc.setContent(file.get()))
			        throw runtime_error(bad_format.toStdString());
			
			    QDomElement root = doc.documentElement(); 
			    if (root.tagName() != "dic")
			        throw runtime_error(bad_format.toStdString());
			
			    QDomElement description_node = root.firstChildElement("description");
			    if (description_node.tagName() != "description")
			        throw runtime_error(bad_format.toStdString());
			 
			    description = description_node.text();
            }
            break;

        case e_csv:
            {
                auto_ptr<QFile> file(new QFile(filename));
                if (!file->open(QIODevice::ReadOnly | QIODevice::Text))
                    throw runtime_error(loading_error.toStdString());
                QTextStream in(file.get());
                in.setFieldWidth(1);
                in.setPadChar('\n');
                
                if (in.atEnd())
                    throw runtime_error(bad_format.toStdString());

                QString buf = in.readLine();
                QStringList lst = buf.split(",");
                if (lst.size() != 2)
                    throw runtime_error(bad_format.toStdString());
                
                if (lst.at(0) != "QWordWizard")
                    throw runtime_error(bad_format.toStdString());

            	description = lst.at(1);
            }
            break;
    }
    return description;
}

void QWWDic::Clear()
{
    m_dictionaries.clear();
}

void QWWDic::Add(bool used, QString filename)
{
    QWWDic_t dic;
    dic.used = used;
    dic.filename = filename;
    m_dictionaries.push_back(dic);
}

void QWWDic::GetDictionariesAttr(QWWDic_attr_t &dic) const
{
    dic.clear();
    for (vector<QWWDic_t>::const_iterator it = m_dictionaries.begin(); it != m_dictionaries.end(); ++it)
    {
        dic.push_back(make_pair(it->used, it->filename));
    }
}

void QWWDic::LoadXML(QString filename)
{

}

void QWWDic::LoadCSV(QWWDic_t *dic) throw (runtime_error)
{
    if (!dic->used)
        return;
    
    auto_ptr<QFile> file(new QFile(dic->filename));
	if (!file->open(QIODevice::ReadOnly | QIODevice::Text))
	    throw runtime_error(loading_error.toStdString());
	QTextStream in(file.get());
	in.setFieldWidth(1);
	in.setPadChar('\n');
	
	if (in.atEnd())
	    throw runtime_error(bad_format.toStdString());
	
	QString buf = in.readLine();
	QStringList lst = buf.split(",");
	if (lst.size() != 2)
	    throw runtime_error(bad_format.toStdString());
	
	if (lst.at(0) != "QWordWizard")
	    throw runtime_error(bad_format.toStdString());
	
	dic->description = lst.at(1);

    while (!in.atEnd())
	{
		buf = in.readLine();
		lst = buf.split(",");

        dic->data.push_back(make_pair(lst.at(0), lst.at(lst.size() - 1)));
	}
}

void QWWDic::GetData(QWWDic_data_t &data) const
{
    if (m_dictionaries.empty())
        return;

    int count = 0;
    for (vector<QWWDic_t>::const_iterator it = m_dictionaries.begin(); it != m_dictionaries.end(); ++it)
    {
        if (it->used)
            count++;
    }
    if (!count)
        return;

    float x;
    int idx_dic;
    int idx_data;
    while (1)
    {
        x = qrand();
    	idx_dic = (float)(x / RAND_MAX * m_dictionaries.size() ) - 1;
        if (m_dictionaries[idx_dic].used)
            break;
    }

    x = qrand();
    idx_data = (float)(x / RAND_MAX * m_dictionaries[idx_dic].data.size() ) - 1;

    data = m_dictionaries[idx_dic].data[idx_data];
}

